package com.tenement.handler;


import cn.hutool.extra.servlet.ServletUtil;
import com.alibaba.fastjson.JSON;
import com.tenement.common.Axios;
import com.tenement.common.GlobalException;
import com.tenement.entity.ExceptionLog;
import com.tenement.enums.RespBusiness;
import com.tenement.service.ExceptionLogService;
import lombok.RequiredArgsConstructor;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
@RequiredArgsConstructor
public class ExceptionInterception {

    private final ExceptionLogService exceptionLogService;

    @ExceptionHandler(GlobalException.class)
    public Axios exceptionHandler(GlobalException exception, HttpServletRequest request)
    {
        ExceptionLog exceptionLog = new ExceptionLog()
                .setType(exception.getStackTrace()[0].getClassName())
                .setName("tenement")
                .setSourceMethod(exception.getStackTrace()[0].getMethodName())
                .setHostMachine(ServletUtil.getClientIP(request))
                .setUserIdentity(request.getRequestedSessionId())
                .setMessage(exception.getMessage())
                .setStackTrace(exception.getStackTrace()[0].toString());
        exceptionLogService.addExceptionLog(exceptionLog);
        return Axios.error(exception.getCode(), exception.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public Axios exceptionHandler(Exception exception, HttpServletRequest request)
    {
        ExceptionLog exceptionLog = new ExceptionLog()
                .setType(exception.getStackTrace()[0].getClassName())
                .setName("tenement")
                .setSourceMethod(exception.getStackTrace()[0].getMethodName())
                .setHostMachine(ServletUtil.getClientIP(request))
                .setUserIdentity(request.getRequestedSessionId())
                .setAdditionalInfo(JSON.toJSONString(exception.getStackTrace()))
                .setMessage(exception.getMessage())
                .setStackTrace(exception.getStackTrace()[0].toString());
        exceptionLogService.addExceptionLog(exceptionLog);
        return Axios.error(500,exception.getMessage());
    }


    @ExceptionHandler(InvocationTargetException.class)
    public Axios exceptionHandler(InvocationTargetException e) {
        return Axios.error(RespBusiness.SERVER_ERROR,e.getMessage());
    }

    @ExceptionHandler(BadCredentialsException.class)
    public Axios exceptionHandler(BadCredentialsException exception) {
        return Axios.error(RespBusiness.PASSWORD_MISMATCH);
    }

    @ExceptionHandler(AccessDeniedException.class)
    public Axios exceptionHandler(AccessDeniedException exception) {
        return Axios.error(RespBusiness.PERMISSION_DENIED);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Axios exceptionHandler(MethodArgumentNotValidException exception) {
        BindingResult bindingResult = exception.getBindingResult();
        Map<String, String> errors = new HashMap<>();
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            errors.put(fieldError.getField(), fieldError.getDefaultMessage());
        }
        return Axios.error(RespBusiness.PARAM_ERROR,errors);
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public Axios exceptionHandler(DuplicateKeyException exception) {
        return Axios.error(RespBusiness.PRESENCE_DATA,"存在重复插入值");
    }


}
